package com.googlecode.cswish.model;

import static com.googlecode.cswish.annotation.GenericType.MODEL;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.googlecode.cswish.annotation.GenericType;


/**
 * an object used to store the page information
 *
 * @author Jerry.Feng Date: 2004-7-4 00:55:00
 * @version $Id: $
 */
public class PageInfo<T> implements Serializable {

	private final static int DISPLAY_RANGE = 5;
	
    // current page Number
    protected int pageNo;
    
    protected int pageSize;

    protected long totalCount;

    // for the irregular page
    protected long firstIndex;
    
    private String desc;
    
    // the search result
    @GenericType(MODEL)
    protected List<T> data;

    public PageInfo() {
	}
    
	public PageInfo(int pageSize) {
		this.pageSize = pageSize;
	}
	
	public PageInfo(List<T> data) {
		this.data = data;
		this.pageSize = data.size();
		if (pageSize == 0) {	// pageSize must be larger than 0
			pageSize = 1;
		}
		this.totalCount = pageSize;
		setPageNo(1);
	}

    public PageInfo(int pageSize, int curPageNo, long totalCount, List<T> data) {
    	this.pageSize = pageSize;
    	if (pageSize == 0) {
			pageSize = 1;
		}
    	setPageNo(curPageNo);
    	this.totalCount = totalCount;
    	this.data = data;
    }

	public int getPageNo() {
		return pageNo < getMinPageNo() ? getMinPageNo():pageNo;
	}

	public void setPageNo(int curPageNo) {
		if (curPageNo <= 0) {
			curPageNo = 1;
		}
		this.pageNo = curPageNo;
	}

	public void setPageNoByRowNo(int rowNo) {
		int pageNo = getPageSize() == 0 ? 1 : (int)rowNo / getPageSize() + 1;
		setPageNo(pageNo);
	}

	public void setTotalCount(long totalRowCount) {
		this.totalCount = totalRowCount;
	}

	public long getTotalCount() {
    	return totalCount;
    }

	@GenericType(MODEL)
    public List<T> getData() {
		return data;
	}
    
	@GenericType(MODEL)
    public T getData(int index) {
    	if (data.size() > index) {
    		return data.get(index);
    	}
    	return null;
    }

	public void setData(List<T> data) {
		this.data = data;
	}
	
	public void setData(Collection<T> data) {
		if (data instanceof ArrayList) {		// freemarker sequence
			this.data = (List<T>) data;
		} else {
			this.data = new ArrayList<T>(data);
		}
	}

	public int getMinPageNo() {
		return 1;
	}

	public int getMaxPageNo() {
		// if the table doesn't exist any data, return 0;
		if (totalCount == 0) {
			return 1;
		}
		if (getPageSize() == 0 ) {
			return 1;
		} else {
			int size = (int)(totalCount - 1) / getPageSize();
			return size + 1;
		}
	}
	
	public int getCurPageStart() {
		if (totalCount == 0) {
			return 0;
		} else {
			return (pageNo - 1) * pageSize + 1;
		}
	}
	
	public int getCurPageEnd() {
		int end = pageNo * pageSize;
		if (end > totalCount) {
			end = (int) totalCount;
		}
		return end;
	}
	
	 public int getDisplayRangeBegin() {
		int begin = pageNo - DISPLAY_RANGE;
		int minPageNo = getMinPageNo();
		if (begin < minPageNo) {
			begin = minPageNo;
		}
		return begin;
	}
	
	public int getDisplayRangeEnd() {
		int end = pageNo + DISPLAY_RANGE;
		int maxPageNo = getMaxPageNo();
		if (end > maxPageNo) {
			end = maxPageNo;
		}
		return end;
	}
	
	// has first page
	public boolean isFirstPage() {
		return getDisplayRangeBegin() != getMinPageNo();
	}
	
	// has last page
	public boolean isLastPage() {
		return getDisplayRangeEnd() != getMaxPageNo();
	}
	
	// has previous page
	public boolean isPrePage() {
	    return pageNo > getMinPageNo();
	}
	
	// has next page
	public boolean isNextPage() {
	    return pageNo < getMaxPageNo();
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public long getFirstIndex() {
		return firstIndex;
	}

	public void setFirstIndex(long firstIndex) {
		this.firstIndex = firstIndex;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}
}